package com.uduemc.biso.node.web.api.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.uduemc.biso.core.extities.center.Site;
import com.uduemc.biso.core.extities.center.SysLanguage;
import com.uduemc.biso.core.utils.JsonResult;
import com.uduemc.biso.core.utils.RestResult;
import com.uduemc.biso.node.core.entities.HDomain;
import com.uduemc.biso.node.core.entities.SArticle;
import com.uduemc.biso.node.core.entities.SCategories;
import com.uduemc.biso.node.core.entities.SPage;
import com.uduemc.biso.node.core.entities.SPdtable;
import com.uduemc.biso.node.core.entities.SPdtableItem;
import com.uduemc.biso.node.core.entities.SProduct;
import com.uduemc.biso.node.core.entities.SSystem;
import com.uduemc.biso.node.core.entities.SSystemItemCustomLink;
import com.uduemc.biso.node.core.feign.SSystemItemCustomLinkFeign;
import com.uduemc.biso.node.core.utils.RestResultUtil;
import com.uduemc.biso.node.core.utils.SiteUrlUtil;
import com.uduemc.biso.node.web.api.component.RequestHolder;
import com.uduemc.biso.node.web.api.pojo.ResponseCustomLink;
import com.uduemc.biso.node.web.api.service.CategoryService;
import com.uduemc.biso.node.web.api.service.DomainService;
import com.uduemc.biso.node.web.api.service.LanguageService;
import com.uduemc.biso.node.web.api.service.PageService;
import com.uduemc.biso.node.web.api.service.SiteService;
import com.uduemc.biso.node.web.api.service.SystemItemCustomLinkService;
import com.uduemc.biso.node.web.api.service.SystemService;
import com.uduemc.biso.node.web.api.service.fegin.SArticleService;
import com.uduemc.biso.node.web.api.service.fegin.SPdtableItemService;
import com.uduemc.biso.node.web.api.service.fegin.SPdtableService;
import com.uduemc.biso.node.web.api.service.fegin.SProductService;
import com.uduemc.biso.node.web.api.validator.currentsite.impl.CurrentSiteSPageRewriteExistValid;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;

@Service
public class SystemItemCustomLinkServiceImpl implements SystemItemCustomLinkService {

	@Autowired
	private RequestHolder requestHolder;

	@Autowired
	private SSystemItemCustomLinkFeign sSystemItemCustomLinkFeign;

	@Autowired
	private PageService pageServiceImpl;

	@Autowired
	private CategoryService categoryServiceImpl;

	@Autowired
	private SystemService systemServiceImpl;

	@Autowired
	private SArticleService sArticleServiceImpl;

	@Autowired
	private SProductService sProductServiceImpl;

	@Autowired
	private DomainService domainServiceImpl;

	@Autowired
	private SPdtableService sPdtableServiceImpl;

	@Autowired
	private SPdtableItemService sPdtableItemServiceImpl;

	@Autowired
	private SiteService siteServiceImpl;

	@Autowired
	private LanguageService languageServiceImpl;

	@Override
	public JsonResult itemCustomLink(long systemId, long itemId) throws IOException {
		Long hostId = requestHolder.getHost().getId();
		Long siteId = requestHolder.getCurrentSite().getId();

		SSystem sSystem = systemServiceImpl.getInfoById(systemId, hostId, siteId);
		if (sSystem == null) {
			return JsonResult.illegal();
		}

		Long systemTypeId = sSystem.getSystemTypeId();
		if (systemTypeId == null) {
			return JsonResult.illegal();
		}

		List<SPage> sPageList = pageServiceImpl.getInfosBySystemId(hostId, siteId, systemId);
		SPage sPage = null;
		if (CollUtil.isNotEmpty(sPageList)) {
			sPage = sPageList.get(0);
		}
		List<String> pathOneGroup = pathOneGroupAndListSPage(hostId, siteId, sPageList);

		RestResult restResult = sSystemItemCustomLinkFeign.pathOneGroup(hostId, siteId);
		@SuppressWarnings("unchecked")
		List<String> pathOneGrupData = (ArrayList<String>) RestResultUtil.data(restResult, new TypeReference<ArrayList<String>>() {
		});
		if (CollUtil.isNotEmpty(pathOneGrupData)) {
			pathOneGroup = CollUtil.addAllIfNotContains(pathOneGroup, pathOneGrupData);
		}
		ResponseCustomLink customLink = new ResponseCustomLink();
		customLink.setPathOneGroup(pathOneGroup);

		String title = null;
		String defaultAccessUrlPath = "";
		if (systemTypeId.longValue() == 1L) {
			// 带分类文章系统
			SArticle sArticle = sArticleServiceImpl.findByIdAndHostSiteSystemId(itemId, hostId, siteId, systemId);
			if (sArticle == null) {
				return JsonResult.illegal();
			}
			title = sArticle.getTitle();
			if (sPage != null) {
				defaultAccessUrlPath = SiteUrlUtil.getPath(sPage, sArticle);
			}
		} else if (systemTypeId.longValue() == 3L) {
			// 带分类产品系统
			SProduct sProduct = sProductServiceImpl.findByIdAndHostSiteSystemId(itemId, hostId, siteId, systemId);
			if (sProduct == null) {
				return JsonResult.illegal();
			}
			title = sProduct.getTitle();
			if (sPage != null) {
				defaultAccessUrlPath = SiteUrlUtil.getPath(sPage, sProduct);
			}
		} else if (systemTypeId.longValue() == 8L) {
			// 带分类产品系统
			SPdtable sPdtable = sPdtableServiceImpl.findByIdAndHostSiteSystemId(itemId, hostId, siteId, systemId);
			if (sPdtable == null) {
				return JsonResult.illegal();
			}
			SPdtableItem sPdtableItem = sPdtableItemServiceImpl.findSPdtableNameByHostSiteSystemPdtableId(sPdtable.getHostId(), sPdtable.getSiteId(),
					sPdtable.getSystemId(), sPdtable.getId());
			title = "";
			if (sPdtableItem != null) {
				title = sPdtableItem.getValue();
			}
			if (sPage != null) {
				defaultAccessUrlPath = SiteUrlUtil.getPath(sPage, sPdtable);
			}
		} else {
			return JsonResult.illegal();
		}

		customLink.setSystemId(systemId).setItemId(itemId).setTitle(title).setDefaultAccessUrlPath(defaultAccessUrlPath);

		List<HDomain> allDomain = domainServiceImpl.allDomain();
		if (CollUtil.isEmpty(allDomain)) {
			return JsonResult.illegal();
		}
		customLink.setListHDomain(allDomain);

		Site defaultSite = siteServiceImpl.getDefaultSite(hostId);
		if (defaultSite == null) {
			return JsonResult.illegal();
		}

		if (defaultSite.getId().longValue() != siteId.longValue()) {
			SysLanguage sysLanguage = languageServiceImpl.getLanguageBySite(requestHolder.getCurrentSite());
			if (sysLanguage == null) {
				return JsonResult.illegal();
			}
			customLink.setLanno("/" + sysLanguage.getLanNo());
		}

		SSystemItemCustomLink sSystemItemCustomLink = findOneByHostSiteSystemItemId(hostId, siteId, systemId, itemId);

		if (sSystemItemCustomLink == null) {
			customLink.setPath(new ArrayList<String>());
			customLink.setStatus((short) 0);
		} else {
			String pathFinal = sSystemItemCustomLink.getPathFinal();
			if (StrUtil.isBlank(pathFinal)) {
				customLink.setPath(new ArrayList<String>());
			} else {
				List<String> split = StrUtil.split(pathFinal, "/");
				List<String> collect = split.stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
				customLink.setPath(collect);
			}
			customLink.setStatus(sSystemItemCustomLink.getStatus());
		}

		return JsonResult.ok(customLink);
	}

	@Override
	public synchronized JsonResult saveItemCustomLink(long systemId, long itemId, short status, String pathFinal, String config) throws IOException {
		Long hostId = requestHolder.getHost().getId();
		Long siteId = requestHolder.getCurrentSite().getId();

		SSystem sSystem = systemServiceImpl.getInfoById(systemId, hostId, siteId);
		if (sSystem == null) {
			return JsonResult.illegal();
		}

		Long systemTypeId = sSystem.getSystemTypeId();
		if (systemTypeId == null) {
			return JsonResult.illegal();
		}

		if (systemTypeId.longValue() == 1L) {
			// 带分类文章系统
			SArticle sArticle = sArticleServiceImpl.findByIdAndHostSiteSystemId(itemId, hostId, siteId, systemId);
			if (sArticle == null) {
				return JsonResult.illegal();
			}
		} else if (systemTypeId.longValue() == 3L) {
			// 带分类产品系统
			SProduct sProduct = sProductServiceImpl.findByIdAndHostSiteSystemId(itemId, hostId, siteId, systemId);
			if (sProduct == null) {
				return JsonResult.illegal();
			}
		} else if (systemTypeId.longValue() == 8L) {
			// 带分类产品系统
			SPdtable sPdtable = sPdtableServiceImpl.findByIdAndHostSiteSystemId(itemId, hostId, siteId, systemId);
			if (sPdtable == null) {
				return JsonResult.illegal();
			}
		} else {
			return JsonResult.illegal();
		}

		if (StrUtil.isBlank(config)) {
			config = "";
		}

		// 如果请求过来的状态为0时，如果存在则直接修改状态为0便可，如果不存在则不做任何动作；
		if (status != 1) {
			updateStatusWhateverByHostSiteSystemItemId(hostId, siteId, systemId, itemId, (short) 0);
			return itemCustomLink(systemId, itemId);
		}

		// 验证 参数是否合法，链接是否重复
		String errorMessage = validItemCustomLink(hostId, siteId, systemId, itemId, pathFinal);
		if (StrUtil.isNotBlank(errorMessage)) {
			return JsonResult.messageError(errorMessage);
		}

		// 写入
		RestResult restResult = null;
		SSystemItemCustomLink data = findOneByHostSiteSystemItemId(hostId, siteId, systemId, itemId);
		if (data == null) {
			// 插入数据
			data = new SSystemItemCustomLink();
			data.setHostId(hostId).setSiteId(siteId).setSystemId(systemId).setStatus(status).setItemId(itemId).setLannoPrefix((short) 1).setPathFinal(pathFinal)
					.setConfig(config);
			restResult = sSystemItemCustomLinkFeign.insert(data);
		} else {
			// 更新数据
			data.setStatus(status).setPathFinal(pathFinal).setConfig(config);
			restResult = sSystemItemCustomLinkFeign.updateByPrimaryKey(data);
		}

		SSystemItemCustomLink save = RestResultUtil.data(restResult, SSystemItemCustomLink.class);
		if (save == null) {
			return JsonResult.assistance();
		}

		return itemCustomLink(systemId, itemId);
	}

	@Override
	public String validItemCustomLink(long hostId, long siteId, long systemId, long itemId, String pathFinal) throws IOException {
		if (StrUtil.isBlank(pathFinal)) {
			return "自定义的链接不能为空。";
		}
		if (NumberUtil.isNumber(pathFinal)) {
			return "自定义链接：" + pathFinal + " 不能全部为数字。";
		}
		if (Pattern.matches(".*\\s.*", pathFinal)) {
			return "自定义链接：" + pathFinal + " 不能存在空格。";
		}

		String[] split = pathFinal.split("/");
		for (String str : split) {
			boolean matches = Pattern.matches("[\\u4e00-\\u9fa5a-zA-Z][\\u4e00-\\u9fa5a-zA-Z0-9\\-]*", str);
			if (!matches) {
				return "自定义链接：" + str + " 错误，链接只能由中文、英文、数字、中横线组成，且每个链接路径不能以数字开头，不能以中横线开头结尾。";
			}
			String sub = StrUtil.sub(str, str.length() - 1, str.length());
			if (sub.equals("-")) {
				return "自定义链接：" + str + " 错误，链接只能由中文、英文、数字、中横线组成，且每个链接路径不能以数字开头，不能以中横线开头结尾。";
			}
		}

		// 1. 首先判断是否系统默认已存在的链接
		String errorMessage = validDefaultSPageRewriteExist(pathFinal);
		if (StrUtil.isNotBlank(errorMessage)) {
			return errorMessage;
		}

		// 2. 查询是否已经存在的页面自定义链接
		errorMessage = validSPageRewriteExist(hostId, siteId, pathFinal);
		if (StrUtil.isNotBlank(errorMessage)) {
			return errorMessage;
		}

		// 3. 查询 s_system_custom_link 是否存在此链接
		SSystemItemCustomLink sSystemItemCustomLink = findOneByHostSiteIdAndPathFinal(hostId, siteId, pathFinal);
		if (sSystemItemCustomLink != null) {
			// 不为空的情况下说明已经存在次自定义链接
			if (itemId > 0) {
				// 验证此 itemId 是否就是这条数据，如果是这条数据没关系，可以增加，如果不是这条数据，则不返回链接已存在。
				if (sSystemItemCustomLink.getSystemId().longValue() != systemId || sSystemItemCustomLink.getItemId().longValue() != itemId) {
					return "自定义链接：" + pathFinal + " 已存。";
				}
			} else {
				// itemId < 1 说明 存在的自定义链接无法新增
				return "自定义链接：" + pathFinal + " 已存。";
			}
		}

		if (split.length == 2) {
			SPage sPage = pageServiceImpl.getInfoByHostSiteIdAndRewrite(hostId, siteId, split[0]);
			if (sPage != null) {
				errorMessage = validDefaultSPageRewriteExist(split[1]);
				if (StrUtil.isNotBlank(errorMessage)) {
					return errorMessage;
				}
				// 是否是已存在的分类链接地址
				SCategories sCategories = categoryServiceImpl.findByHostSiteIdAndRewrite(hostId, siteId, split[1]);
				if (sCategories != null) {
					return "自定义链接：" + pathFinal + " 已存。";
				}
			}
		}

		if (split.length == 3) {
			if (split[1].equals("item")) {
				return "链接路径中不能使用 item 关键字。";
			}
		}

		return null;
	}

	@Override
	public String validDefaultSPageRewriteExist(String pathFinal) throws IOException {
		List<Map<String, String>> defaultRewrite = CurrentSiteSPageRewriteExistValid.defaultRewrite;
		for (Map<String, String> pattern : defaultRewrite) {
			if (CurrentSiteSPageRewriteExistValid.isMatch(pattern.get("pattern"), pathFinal)) {
				return pattern.get("message");
			}
		}
		return null;
	}

	@Override
	public String validSPageRewriteExist(long hostId, long siteId, String pathFinal) throws IOException {
		SPage sPage = pageServiceImpl.getInfoByHostSiteIdAndRewrite(hostId, siteId, pathFinal);
		if (sPage != null) {
			return pathFinal + " 已存在，页面：" + sPage.getName() + "。";
		}
		return null;
	}

	@Override
	public SSystemItemCustomLink findOneByHostSiteIdAndPathFinal(long hostId, long siteId, String pathFinal) throws IOException {
		RestResult restResult = sSystemItemCustomLinkFeign.findOneByHostSiteIdAndPathFinal(hostId, siteId, pathFinal);
		SSystemItemCustomLink data = RestResultUtil.data(restResult, SSystemItemCustomLink.class);
		return data;
	}

	@Override
	public SSystemItemCustomLink findOneByHostSiteSystemItemId(long hostId, long siteId, long systemId, long itemId) throws IOException {
		RestResult restResult = sSystemItemCustomLinkFeign.findOneByHostSiteSystemItemId(hostId, siteId, systemId, itemId);
		SSystemItemCustomLink data = RestResultUtil.data(restResult, SSystemItemCustomLink.class);
		return data;
	}

	@Override
	public SSystemItemCustomLink findOkOneByHostSiteSystemItemId(long hostId, long siteId, long systemId, long itemId) throws IOException {
		RestResult restResult = sSystemItemCustomLinkFeign.findOkOneByHostSiteSystemItemId(hostId, siteId, systemId, itemId);
		SSystemItemCustomLink data = RestResultUtil.data(restResult, SSystemItemCustomLink.class);
		return data;
	}

	@Override
	public List<String> pathOneGroupAndSystemId(long systemId) throws IOException {
		Long hostId = requestHolder.getHost().getId();
		Long siteId = requestHolder.getCurrentSite().getId();
		return pathOneGroupAndSystemId(hostId, siteId, systemId);
	}

	@Override
	public List<String> pathOneGroupAndSystemId(long hostId, long siteId, long systemId) throws IOException {
		List<SPage> sPageList = pageServiceImpl.getInfosBySystemId(hostId, siteId, systemId);
		return pathOneGroupAndListSPage(hostId, siteId, sPageList);
	}

	@Override
	public List<String> pathOneGroupAndListSPage(long hostId, long siteId, List<SPage> sPageList) throws IOException {
		List<String> pathOneGroup = new ArrayList<>();
		if (CollUtil.isNotEmpty(sPageList)) {
			for (SPage item : sPageList) {
				if (StrUtil.isNotBlank(item.getRewrite())) {
					pathOneGroup.add(item.getRewrite());
				}
			}
		}
		if (CollUtil.size(pathOneGroup) > 1) {
			pathOneGroup = CollUtil.distinct(pathOneGroup);
		}

		RestResult restResult = sSystemItemCustomLinkFeign.pathOneGroup(hostId, siteId);
		@SuppressWarnings("unchecked")
		List<String> pathOneGrupData = (ArrayList<String>) RestResultUtil.data(restResult, new TypeReference<ArrayList<String>>() {
		});
		if (CollUtil.isNotEmpty(pathOneGrupData)) {
			pathOneGroup = CollUtil.addAllIfNotContains(pathOneGroup, pathOneGrupData);
		}
		return pathOneGroup;
	}

	@Override
	public int deleteByHostSiteSystemItemId(long hostId, long siteId, long systemId, long itemId) throws IOException {
		RestResult restResult = sSystemItemCustomLinkFeign.deleteByHostSiteSystemItemId(hostId, siteId, systemId, itemId);
		return RestResultUtil.data(restResult, Integer.class);
	}

	@Override
	public int updateStatusWhateverByHostSiteSystemItemId(long hostId, long siteId, long systemId, long itemId, short status) throws IOException {
		RestResult restResult = sSystemItemCustomLinkFeign.updateStatusWhateverByHostSiteSystemItemId(hostId, siteId, systemId, itemId, status);
		return RestResultUtil.data(restResult, Integer.class);
	}

}
